package visualization;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

public class JScatterPlot extends Canvas {
	
	String xlabel = "X";
	String ylabel = "Y";
	String title = "Scatter-plot";
	
	double minx = -200, maxx = 200, miny = -200, maxy = 200;
	
	int inset = 48;
	int gx0, gy0, gw, gh, cx, cy;
	double xscale, yscale;
	
	public JScatterPlot() {
		setSize(400, 300);
		setBackground(Color.lightGray);
		
		data = new double[10][2];
		for (int i = 0; i < 10; i++) data[i] = new double[]{ Math.random()*400-200, Math.random()*400-200 };
		
		render();
	}
	
	double[][] data = null;
	
	/**
	 * Override this method to set custom data.
	 * 
	 * @return
	 */
	public double[][] getData() {
		return data;
	}
	
	BufferedImage img = null;
	
	Font tickFont = new Font("Verdana", Font.PLAIN, 8);
	Font titleFont = new Font("Arial", Font.PLAIN, 14);
	
	public void render()
	{
		int w = getWidth();
		int h = getHeight();
		img = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
		gx0 = inset*2; gy0 = inset; gw = w-inset*3; gh = h-inset*2;
		cx = gx0 + gw/2; cy = gy0 + gh/2;

		Graphics2D g2 = img.createGraphics();
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		
		g2.setColor(Color.lightGray);
		g2.fillRect(0, 0, w, h);
		
		g2.setColor(Color.white);
		g2.fillRect(gx0, gy0, gw, gh);

		g2.setColor(Color.black);
		
		// draw borders
		g2.drawLine(gx0, gy0, gx0+gw, gy0); // upper horizontal
		g2.drawLine(gx0, gy0+gh, gx0+gw, gy0+gh); // lower horizontal
		
		g2.drawLine(gx0, gy0, gx0, gy0+gh); // left vertical
		g2.drawLine(gx0+gw, gy0, gx0+gw, gy0+gh); // right vertical
		
		// draw title
		g2.setFont(titleFont);
		g2.drawString(title, gx0+gw/4, gy0-inset/2+8);
		
		// draw axes
		g2.drawString(xlabel, gx0+gw/2, gy0+gh+inset);  // X
		g2.drawString(ylabel, gx0-inset-16, gy0+gh/2+32); // Y
		
		// draw ticks
		double xrng = maxx - minx;
		double xstep = 10 * (Math.round(xrng / 100.0));
		for (double x = minx; x <= maxx; x += xstep) {
			double scrX = gx0 + (x-minx)*gw/xrng;
			double scrY = gy0+gh;
			
			// tick
			g2.setColor(Color.black);
			g2.drawLine((int)scrX, (int)scrY, (int)scrX, (int)(scrY+5));
			g2.setFont(tickFont);
			g2.drawString(String.format("%.2f", x), (int)scrX-10, (int)scrY+15);
			
			// grid 
			g2.setColor(Color.lightGray);
			g2.drawLine((int)scrX, gy0, (int) scrX, gy0+gh);
		}

		double yrng = maxy - miny;
		double ystep = 10 * (Math.round(yrng / 100.0));
		for (double y = miny; y <= maxy; y += ystep) {
			double scrX = gx0;
			double scrY = gy0+gh-(y-miny)*gh/yrng;
			
			// tick
			g2.setColor(Color.black);
			g2.drawLine((int)scrX-5, (int)scrY, (int)scrX, (int)scrY);
			g2.setFont(tickFont);
			g2.drawString(String.format("%.2f", y), (int)scrX-40, (int)scrY+5);
			
			// grid 
			g2.setColor(Color.lightGray);
			g2.drawLine(gx0, (int)scrY, gx0+gw, (int) scrY);

		}

		
		// draw data		
		xscale = gw / xrng;
		yscale = gh / yrng;
		double[][] dd = getData();
		for (double[] d : dd) {
			double scrX = gx0 + (d[0]-minx)*gw/xrng;			
			double scrY = gy0+gh-(d[1]-miny)*gh/yrng;
			g2.setColor(Color.blue);
			g2.fillArc((int)scrX, (int)scrY, 2, 2, 0, 360);
		}
		
		paintOverlay(g2);
	}
	
	/**
	 * Override this method to paint overlay objects.
	 * @param g
	 */
	public void paintOverlay(Graphics2D g)
	{
	}

	@Override
	public void paint(Graphics g) {
		((Graphics2D)g).drawImage(img, null, 0, 0);
	}

	
	public static void main(String[] args) {
		JFrame jf = new JFrame("JScatterPlot");
		jf.setSize(500,500);
		jf.add(new JScatterPlot());
		jf.setVisible(true);
	}
}
